package com.fita.wechat.web.controller;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import com.demo2do.core.entity.exception.BusinessException;
import com.demo2do.core.entity.result.HttpResult;
import com.demo2do.core.utils.CollectionUtils;
import com.demo2do.core.utils.DateUtils;
import com.demo2do.core.utils.JsonUtils;
import com.demo2do.core.web.utils.WebUtils;
import com.demo2do.core.wechat.entity.cfg.JsConfig;
import com.fita.entity.agent.Agent;
import com.fita.entity.car.VehicleCategory;
import com.fita.entity.car.VehicleSize;
import com.fita.entity.coupon.Coupon;
import com.fita.entity.data.Country;
import com.fita.entity.data.Location;
import com.fita.entity.data.Supplier;
import com.fita.entity.dto.ehi.response.LocationDetailResponse;
import com.fita.entity.order.Order;
import com.fita.entity.order.OrderSpecialEquipment;
import com.fita.entity.order.OrderVehicleFee;
import com.fita.entity.order.PayType;
import com.fita.entity.set.Set;
import com.fita.wechat.Constant;
import com.fita.wechat.entity.CarDetail;
import com.fita.wechat.entity.Shopping;
import com.fita.wechat.entity.security.Login;
import com.fita.wechat.handler.EhiHandler;
import com.fita.wechat.handler.PDFHandler;
import com.fita.wechat.processor.WechatProcessor;
import com.fita.wechat.service.AgentService;
import com.fita.wechat.service.CarService;
import com.fita.wechat.service.CouponService;
import com.fita.wechat.service.DataService;
import com.fita.wechat.service.OrderService;
import com.fita.wechat.service.SetService;
import com.fita.wechat.web.interceptor.Mobile;
import com.fita.wechat.web.interceptor.Wechat;
import com.fita.wechat.web.resolver.Secure;


/**
 * 
 * @author 宋剑宏
 *
 */
@Controller
@RequestMapping("/shopping")
public class ShoppingController {
    
    private static final Logger logger = LoggerFactory.getLogger(ShoppingController.class);
    
    private static final String USER_AGENT = "User-Agent";
    
    private static final String MICRO_MESSENGER = "MicroMessenger";
    
    @Value("#{ctx['ctx.domain']}")
    private String domain;
    
    @Autowired
    private CouponService couponService;
    
    @Autowired
    @Qualifier("dataService")
    private DataService<Location> locationService;
    
    @Autowired
    @Qualifier("dataService")
    private DataService<Supplier> supplierService;
    
    @Autowired
    @Qualifier("dataService")
    private DataService<Country> countryService;
    
    @Autowired
    private SetService setService;
    
    @Autowired
    private AgentService agentService;
    
    @Autowired
    private OrderService orderService;
    
    @Autowired
    private WechatProcessor wechatProcessor;
    
    @Autowired
    private CarService carService;
    
    @Autowired
    private EhiHandler ehiHandler;
    
    @Autowired
    private PDFHandler pdfHandler;
    
    
    /**
     * 
     * @return
     */
    @RequestMapping(value = "/handpay-test", method = RequestMethod.GET)
    public ModelAndView handPayTest() {
        ModelAndView modelAndView = new ModelAndView("shopping/handpay-form");
        
        Order order = new Order();
        order.setCode("TEST-Handpay-Code");
        order.setPayPrice(100);
        order.setCurrentExchangeRate(new BigDecimal(1));
        order.setType(PayType.PREPAY);
        order.setBrand("Alamo");
        
        String openid = "oJ9WO1l9x4c4xOr2_FzpvF5xpVLI";
        
        Map<String, Object> payConfig = orderService.handpay(order, openid);
        modelAndView.addObject("payConfig", payConfig);
        
        return modelAndView;
    }
    
    /**
     * 
     * @return
     */
    @RequestMapping(value = "/handpay-success", method = RequestMethod.POST)
    public ModelAndView handpaySuccess() {
        ModelAndView modelAndView = new ModelAndView("shopping/handpay-success");
        return modelAndView;
    }

    /**
     * 用户信息填写页
     * 
     * @return
     */
    @Wechat
    @Mobile
    @RequestMapping(value = "/user-info", method = RequestMethod.POST)
    public ModelAndView userInformation(@Secure Login login, CarDetail carDetail) {
        
        ModelAndView modelAndView = new ModelAndView("shopping/user-info");
        modelAndView.addObject("carDetail", carDetail);
        
        Location pickupLocation = locationService.load(Location.class, carDetail.getPickupLocation());
        Location returnLocation = locationService.load(Location.class, carDetail.getReturnLocation());
        modelAndView.addObject("pickupLocation", pickupLocation);
        modelAndView.addObject("returnLocation", returnLocation);
        modelAndView.addObject("carsDetailString", JsonUtils.toJson(carDetail));
        
        int days = DateUtils.daysBetween(carDetail.getPickupDate(), carDetail.getReturnDate());
        modelAndView.addObject("days", days);
        
        // 获取当前选择价格
        Set set = setService.load(carDetail.getSetId());
        modelAndView.addObject("set", set);
        
        // 获取当前代理公司
        Agent agent = agentService.load(login.getId());
        modelAndView.addObject("agentCompany", agent.getCompany());

        modelAndView.addObject("agent", agent);
        
        return modelAndView;
    }

    /**
     * 用户信息提交 保存新用户信息，同时将该用户信息关联到shopping
     * 
     * @return
     */
    @Wechat
    @Mobile
    @RequestMapping(value = "/order", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult order(@Secure Login login, Shopping shopping) {
        HttpResult httpResult = new HttpResult();
        
        try {
            
            Map<String, Object> params = carService.generateLocationDetailParams(shopping);
            LocationDetailResponse locationDetail =  ehiHandler.loadLocationDetail(params);
            
            Agent agent = agentService.load(login.getId());
            Order order = orderService.create(agent, shopping, locationDetail);
            
            httpResult.success().message("订单创建成功").data("order", order);
            
        } 
        catch (BusinessException e) {
            logger.error("create order occurs error", e);
            httpResult.fail("500").message(e.getMessage());
		}
        catch (Exception e) {
            logger.error("create order occurs error", e);
            httpResult.fail("500").message("订单创建失败");
        }
        return httpResult;

    }

    /**
     * 订单确认页面（展示shopping的所有信息）
     * 
     * @param id
     * @return
     */
    @Wechat
    @Mobile
    @RequestMapping(value = "/orders/{id}", method = RequestMethod.GET)
    public ModelAndView orderAck(@PathVariable Long id,
                                 @Secure Login login) {
        ModelAndView modelAndView = new ModelAndView("shopping/shopping-orders-ack");
        
        Order order = orderService.load(id);
        modelAndView.addObject("order", order);
        
        Location pickupLocation = locationService.load(Location.class, "code", order.getPickupLocation());
        Location returnLocation = locationService.load(Location.class, "code", order.getReturnLocation());
        modelAndView.addObject("pickupLocation", pickupLocation);
        modelAndView.addObject("returnLocation", returnLocation);
        
        Supplier supplier = supplierService.load(Supplier.class, "code", order.getBrand());
        modelAndView.addObject("supplier", supplier);
        
        Country country = countryService.load(Country.class, "code", order.getCountry());
        modelAndView.addObject("country", country);
        
        Set set = setService.load(order.getDetails().getSetMeal());
        modelAndView.addObject("set", set);
        
        int days = DateUtils.daysBetween(order.getPickupDate(), order.getReturnDate());
        modelAndView.addObject("days", days);
        
        // list order special equipment
        List<OrderSpecialEquipment> equipments = orderService.listSpecialEquipment(order);
        modelAndView.addObject("equipments", equipments);
        
        // list order vehicle fee
        List<OrderVehicleFee> orderVehicleFees = orderService.listVehicleFee(order);
        Map<String, List<OrderVehicleFee>> vehicleFees = CollectionUtils.constructMapValues(orderVehicleFees, "include");
        modelAndView.addObject("include", vehicleFees.get("true"));
        modelAndView.addObject("unInclude", vehicleFees.get("false"));
        
        // TODO load location detail here for order detail

        Agent agent = agentService.load(login.getId());

        modelAndView.addObject("agent", agent);

        return modelAndView;

    }

    /**
     * 保留订单
     * 
     * @return
     */
    @Wechat
    @Mobile
    @RequestMapping(value = "/orders/{id}/staying", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult stayingOrder(@PathVariable Long id) {
        
        HttpResult httpResult = new HttpResult();
        
        try {
            
            Order order = orderService.load(id);
            orderService.staying(order.staying());
            
            httpResult.success().message("订单保留成功").data("order", order).data("agent", order.getAgent());
            
        } catch (Exception e) {
            logger.error("staying order occurs error", e);
            httpResult.fail("500").message("订单保留失败");
        }

        return httpResult;
    }
    
    /**
     * 
     * @param orderId
     * @return
     */
    @Wechat
    @Mobile
    @RequestMapping(value = "/orders/{id}/paying", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult payingOrder(@PathVariable("id") Long orderId) {
        
        HttpResult httpResult = new HttpResult();
        
        try {
            orderService.paying(orderId);
            
            Order order = orderService.load(orderId);
            
            httpResult.success().message("付款中成功").data("order", order).data("agent", order.getAgent());
            
        }catch (BusinessException e) {
        	
            logger.error("payingOrder occurs error", e);
            
            httpResult.fail(e.getCode()).message(e.getMessage());
            
        }catch (Exception e) {
        	
            logger.error("payingOrder occurs error", e);
            
            httpResult.fail("500").message("付款中失败");
        }
        return httpResult;
    }
    
    @Wechat
    @Mobile
    @RequestMapping(value = "/orders/{id}/arrive-paying", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult payingArriveOrder(@PathVariable("id") Long orderId) {
        
        HttpResult httpResult = new HttpResult();
        
        try {
            orderService.arrivePay(orderId);
            
            Order order = orderService.load(orderId);
            
            httpResult.success().message("订单生成成功").data("order", order).data("agent", order.getAgent());
            
        } catch (Exception e) {
        	
            logger.error("payingArriveOrder occurs error", e);
            
            httpResult.fail("500").message("订单生成失败");
        }
        return httpResult;
    }
    
    

    /**
     * 获取结果页
     * 
     * @return
     */
    @Wechat
    @Mobile
    @RequestMapping(value = "/result", method = RequestMethod.GET)
    public ModelAndView result(@Secure Login login,
                               @RequestParam("type") String type,
                               @RequestParam("orderId") Long orderId,
                               HttpServletRequest request) {
        
        ModelAndView modelAndView = new ModelAndView();
        
        Order order = orderService.load(orderId);
        modelAndView.addObject("order", order);
        
        Location pickupLocation = locationService.load(Location.class, "code", order.getPickupLocation());
        Location returnLocation = locationService.load(Location.class, "code", order.getReturnLocation());
        modelAndView.addObject("pickupLocation", pickupLocation);
        modelAndView.addObject("returnLocation", returnLocation);
        
        Supplier supplier = supplierService.load(Supplier.class, "code", order.getBrand());
        modelAndView.addObject("supplier", supplier);
        
        Country country = countryService.load(Country.class, "code", order.getCountry());
        modelAndView.addObject("country", country);
        
        Set set = setService.load(order.getDetails().getSetMeal());
        modelAndView.addObject("set", set);
        
        int days = DateUtils.daysBetween(order.getPickupDate(), order.getReturnDate());
        modelAndView.addObject("days", days);
        

        if (StringUtils.equalsIgnoreCase(type, "staying")) {
            modelAndView.setViewName("shopping/staying-orders-info-result");
        } else {
            
            String curl = WebUtils.getRealRequestURL(request);
            JsConfig jsConfig = wechatProcessor.generateJsConfig(curl);
            modelAndView.addObject("jsConfig", JsonUtils.toJson(jsConfig));
            modelAndView.setViewName("shopping/orders-info-result");
            
            //是否微信环境
            boolean isMicroMessenger = this.isMicroMessenger(request);
            modelAndView.addObject("isMicroMessenger", isMicroMessenger);
            logger.info("cnyPrice [{}]",order.getCnyPayPrice());
          //展示所有可使用，包括被占用的优惠券
            List<Coupon> coupons = couponService.listAllAvailableCoupons(order.getAgent().getId(),order.getCnyPayPrice());
            logger.info("orderRetailAmount [{}] couponSize [{}]",order.getRetailAmount(),coupons.size());
            modelAndView.addObject("coupons",JsonUtils.toJson(coupons));
        }
        if(order.getUserCouponId() != null){

            Coupon userCoupon = couponService.load(order.getUserCouponId());
            modelAndView.addObject("userCoupon",userCoupon);
            
            boolean needpay = (order.getCnyPayPrice().intValue() - (userCoupon.getAmount()/100) > 0) ? true : false;
            modelAndView.addObject("needpay", needpay);
        } else {
            modelAndView.addObject("needpay", true);
        }
        

        // ，获取已有用户信息（optional）
        return modelAndView;
    }
    
    
    @Wechat
    @Mobile
    @RequestMapping(value = "/bind", method = RequestMethod.POST,produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult useCoupon(@RequestParam( value = "orderId") Long orderId,
                               @RequestParam(value = "couponId" ) Long couponId,
                               HttpServletRequest request) {
    	
    	HttpResult httpResult = new HttpResult();

    	//优惠券绑定订单
    	if(couponId == 0 ){

            couponService.unBindCoupon(orderId);
            return httpResult.success().data("couponStatus", null);
        }
    	Coupon  coupon = couponService.bindCoupon(orderId,couponId);

    	return httpResult.success().data("couponStatus", coupon.getStatus());
    }

    //0元支付接口
    @RequestMapping(value = "otherPay" ,method = RequestMethod.POST,produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult onOtherPay(@RequestParam("order") Long orderId,
                                               @RequestParam("currentUrl") String currentUrl,
                                               HttpServletRequest request){
        HttpResult httpResult = new HttpResult();


        //订单改为支付状态
        //优惠券改为使用状态

        orderService.otherPay(orderId);


        return  httpResult.success().message("支付成功");

    }


    /**
     * 
     * @param orderId
     * @param currentUrl
     * @param request
     * @return
     */
    @RequestMapping(value = "/pay", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult onPay(@RequestParam("order") Long orderId, 
                                          @RequestParam("type") String type, 
                                          @RequestParam("currentUrl") String currentUrl,
                                          HttpServletRequest request) {
        
        HttpResult httpResult = new HttpResult();
        
        Order order = orderService.load(orderId);

        // 1. create order & payment request
        String xRealIpHeader = request.getHeader("X-Real-IP");  // Only available after NGINX redirect
        String remoteIp = StringUtils.isBlank(xRealIpHeader) ? request.getRemoteAddr() : xRealIpHeader;
        logger.trace("#join() - Get remote IP address [{}].", remoteIp);

        Cookie cookie = org.springframework.web.util.WebUtils.getCookie(request, Constant.OPENID_KEY);
        //使用优惠券
        String redirectUrl = domain + "/shopping/"+ orderId + "/result-success";
        String openid = cookie == null ? order.getAgent().getId().toString() : cookie.getValue();
        Map<String, Object> data = orderService.prepay(order, openid, remoteIp,order.getUserCouponId(), type, redirectUrl);
        String paypage = data.get("url").toString();
        
        
        return httpResult.success()
                         .data("paypage", paypage)
                         .data("order", order.getId());
    }
    
    /**
     * 获取结果页-成功
     * 
     * @return
     */
    @Wechat
    @Mobile
    @RequestMapping(value = "/result-success", method = RequestMethod.GET)
    public ModelAndView resultSuccess(@RequestParam("orderId") Long orderId) {
        ModelAndView modelAndView = new ModelAndView("shopping/orders-result-success");
        
        Order order = orderService.load(orderId);
        
        //coupon 状态改成 已使用
        couponService.useCoupon(order);

        modelAndView.addObject("order", order);
        
        return modelAndView;
    }
    
    /**
     * 获取结果页-成功
     * 
     * @return
     */
    @Wechat
    @Mobile
    @RequestMapping(value = "/{id}/result-success", method = RequestMethod.GET)
    public ModelAndView resultSuccess2(@PathVariable("id") Long orderId) {
        ModelAndView modelAndView = new ModelAndView("shopping/orders-result-success");
        
        Order order = orderService.load(orderId);
        
        //coupon 状态改成 已使用
        couponService.useCoupon(order);

        modelAndView.addObject("order", order);
        
        return modelAndView;
    }
    
    /**
     * 
     * @param request
     * @return
     */
    private boolean isMicroMessenger(HttpServletRequest request) {
        
        String userAgent = request.getHeader(USER_AGENT);
        logger.info("#isMicroMessenger() - Get user agent [{}].", userAgent);
        
        return org.apache.commons.lang3.StringUtils.isNoneBlank(userAgent) && userAgent.indexOf(MICRO_MESSENGER) >= 0;
    }
    
    @RequestMapping(value = "/orders/{id}/order-confirm", method = RequestMethod.GET)
    public String confirmReport(@PathVariable Long id) {
        
        Order order = orderService.load(id);
        
        Location pickupLocation = locationService.load(Location.class, "code", order.getPickupLocation());
        Location returnLocation = locationService.load(Location.class, "code", order.getReturnLocation());
        
        Set set = setService.load(order.getDetails().getSetMeal());
        
        // list order special equipment
        List<OrderSpecialEquipment> equipments = orderService.listSpecialEquipment(order);
        
        // list order vehicle fee
        List<OrderVehicleFee> orderVehicleFees = orderService.listVehicleFee(order);
        Map<String, List<OrderVehicleFee>> vehicleFees = CollectionUtils.constructMapValues(orderVehicleFees, "include");
        
        String vehicleSize = VehicleSize.ssipOf(order.getDetails().getCarInfo().getModelCodeClass()).getChineseName();
        String vehicleCategory = VehicleCategory.codeOf(order.getDetails().getCarInfo().getCategoryCode()).getChineseName();
        
        String result = pdfHandler.saveOrderConfirm(order, pickupLocation, returnLocation, set, vehicleFees.get("true"), vehicleFees.get("false"), equipments, vehicleSize, vehicleCategory);
        
        return result;

    }
}
